package cn.xiongxf.service.impl;

import cn.xiongxf.constant.RedisKeyConstant;
import cn.xiongxf.domain.KillActivity;
import cn.xiongxf.domain.KillCourse;
import cn.xiongxf.mapper.KillActivityMapper;
import cn.xiongxf.service.IKillActivityService;
import cn.xiongxf.service.IKillCourseService;
import cn.xiongxf.util.AssertUtil;
import cn.xiongxf.util.StrUtils;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RSemaphore;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author xiongxiaofu
 * @since 2022-09-01
 */
@Service
@Slf4j
public class KillActivityServiceImpl extends ServiceImpl<KillActivityMapper, KillActivity> implements IKillActivityService {
    @Autowired
    private IKillCourseService killCourseService;
    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;
    @Autowired
    private RedissonClient redissonClient;

    /**
     * 秒杀活动新增
     */
    @Override
    public void save(KillActivity killActivity) {
        killActivity.setCreateTime(new Date());
        killActivity.setPublishStatus(KillActivity.STATUS_WAIT_PUBLISH);
        // 时间格式化处理
        SimpleDateFormat dateFormat = new SimpleDateFormat("MM-dd HH:mm:ss");
        String timeStr = dateFormat.format(killActivity.getStartTime());
        killActivity.setTimeStr(timeStr);

        // 保存秒杀活动对象
        insert(killActivity);

    }

    /**
     * 秒杀活动发布
     */
    @Override
    public void publish(Long activityId) {
        // 1.秒杀活动非空校验
        KillActivity killActivity = selectById(activityId);
        AssertUtil.isNotNull(killActivity, "秒杀活动不存在！");

        // 2.判断秒杀活动是否已发布
        AssertUtil.isEquals(killActivity.getPublishStatus(), KillActivity.STATUS_WAIT_PUBLISH, "秒杀活动已发布！");

        // 3.查询秒杀活动中的所有商品
        List<KillCourse> killCourses = killCourseService.selectList(new EntityWrapper<KillCourse>().eq("activity_id", activityId));
        AssertUtil.isNotNull(killCourses, "秒杀活动中没有商品！");

        // 4.修改秒杀活动对象
        killActivity.setPublishStatus(KillActivity.STATUS_SUCCESS_PUBLISH);
        killActivity.setPublishTime(new Date());
        updateById(killActivity);

        // 遍历，修改所有秒杀商品
        killCourses.forEach(killCourse -> {
            // # 秒杀商品的库存，使用信号量存入Redis
            RSemaphore semaphore = redissonClient.getSemaphore(RedisKeyConstant.KILL_COURSE_STORE + killCourse.getId());
            boolean success = semaphore.trySetPermits(killCourse.getKillCount());
            if (success){
                killCourse.setPublishStatus(killActivity.getPublishStatus());
                // 秒杀码
                killCourse.setCode(StrUtils.getComplexRandomString(6));
                // # 把秒杀商品存入Redis - hash
                redisTemplate.opsForHash().put(RedisKeyConstant.KILL_COURSES, killCourse.getId().toString(), killCourse);

                killCourse.setPublishTime(killActivity.getPublishTime());
                killCourseService.updateById(killCourse);

                log.info("发布秒杀课程成功：{}", killCourse);
            }else {
                log.info("发布秒杀课程失败：{}", killCourse);
            }
        });
    }


}
